2026-01-21
Locks
Data structure that can be locked and unlocked.
Several threads share and access the same lock. Exactly one thread acquires the lock, all other threads are blocked until this thread unlocks the lock.
This means that you can easily create code that does not interfere with other threads:
int cnt;
lock.lock();
cnt = counter;
counter = cnt + 1;
lock.unlock();
Context switches can only happen outside of the lock, since all other threads are blocked.
Locks in java
The java.util.concurrent.locks package contains the Lock interface.
Always use finally to ensure that the thread unlocks the lock even if an error should occur:
try {
// Other code
} finally {
lock.unlock();
}
Synchronized
Using these classes is cumbersome. The synchronized method modifier will lock and unlock this implicitly for the entire execution of the method. You can also lock blocks and specify which object should be locked:
synchronized(this) {
// Locks `this` until exiting the block.
}
Reenter
The ReentrantLock class implements Lock and allows threads to reenter the same lock. This means that if the same thread calls lock() multiple times this is fine and won't be blocked. This can be used for nested methods where the inner and outer methods both need to be locked. However this adds extra overhead to the shared memory, so if you know you won't need it, use a simpler lock.
Invariants
A condition that holds:
- initially, just after object creation
- when the method call starts
- when the method call ends
This however assumes that only one method is run and changing the object at the same time.
Semaphores
Regulate access to a finite number of resources, if there are no resources available the thread will be blocked.
up (or signal) releases a resource
down (or wait) acquires a resource
Semaphores have the invariant:
count() >= 0;
count() == C + #up - #down;
Binary semaphore
A binary semaphore always has a count of at most 1. This is not a unique type of semaphore but a use-case.
This sounds a lot like a lock, however there is one important difference: In a semaphore, any thread can up the semaphore, not just the thread with the resource.
Semaphores in Java
The Semaphore class:
permits: How many tickets to start withacquire(): down the semaphorerelease(): up the semaphoretryAcquire(): Try to down the semaphore, returnsfalseon fail instead of blockingavailablePermits(): Check how many tickets are available
The method acquire() may throw InterruptedException which must be handled.
Barriers
Barriers allow you to define a point where all threads in a group have to reach before any are allowed to progress.
This can be implemented with semaphores, where a thread will up their own semaphore and down the other thread's semaphore to check that everyone is done.
Barriers are reusable and never get out of sync.